
#include <librally.h>

//======================================================================

typedef unsigned int (*HashFunc)(char*, unsigned int);

unsigned int rp_hash(char *str, unsigned int len, HashFunc hf)
{
	static char fname[] = "rp_hash";
	static char msg[] = "fatal error";
	Err err;
	static HashFunc hash = NULL;
	unsigned int value;
	FLOG_IN(fname);

	if (!hf) hash = hf;
	value = hash(str, len);

	FLOG_OUT(fname);
	return value;
}

unsigned int rp_hash_rs(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_rs";
	static char msg[] = "fatal error";
	Err err;
	unsigned int b    = 378551;
	unsigned int a    = 63689;
   	unsigned int value = 0;
   	unsigned int i    = 0;
	FLOG_IN(fname);
	
   	for(i = 0; i < len; str++, i++)
   	{
      		value = value * a + (*str);
      		a    = a * b;
   	}

	FLOG_OUT(fname);
	return value;
}

unsigned int rp_hash_js(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_js";
	static char msg[] = "fatal error";
	Err err;
	unsigned int value = 1315423911;
   	unsigned int i    = 0;
	FLOG_IN(fname);

	for(i = 0; i < len; str++, i++)
   	{
      		value ^= ((value << 5) + (*str) + (value >> 2));
   	}
	
	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_pjw(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_pjw";
	static char msg[] = "fatal error";
	Err err;
   	const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
   	const unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt  * 3) / 4);
   	const unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
   	const unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
   	unsigned int value = 0;
   	unsigned int test = 0;
   	unsigned int i = 0;

   	for(i = 0; i < len; str++, i++)
   	{
      		value = (value << OneEighth) + (*str);

      		if ((test = value & HighBits)  != 0)
      		{
         		value = ((value ^ (test >> ThreeQuarters)) & (~HighBits));
      		}
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_elf(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_elf";
	static char msg[] = "fatal error";
	Err err;
	unsigned int value = 0;
   	unsigned int x = 0;
   	unsigned int i  = 0;
	FLOG_IN(fname);
	
   	for(i = 0; i < len; str++, i++)
   	{
      		value = (value << 4) + (*str);
      		if ((x = value & 0xF0000000L) != 0)
      		{
         		value ^= (x >> 24);
      		}
      		value &= ~x;
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_bkdr(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_bkdr";
	static char msg[] = "fatal error";
	Err err;
	unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */
   	unsigned int value = 0;
   	unsigned int i    = 0;
	FLOG_IN(fname);

   	for(i = 0; i < len; str++, i++)
   	{
      		value = (value * seed) + (*str);
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_sdbm(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_sdbm";
	static char msg[] = "fatal error";
	Err err;
   	unsigned int value = 0;
   	unsigned int i = 0;
	FLOG_IN(fname);
	
   	for (i = 0; i < len; str++, i++)
   	{
      		value = (*str) + (value << 6) + (value << 16) - value;
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_djb(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_djb";
	static char msg[] = "fatal error";
	Err err;
   	unsigned int value = 5381;
   	unsigned int i    = 0;
	FLOG_IN(fname);
	
   	for (i = 0; i < len; str++, i++)
   	{
      		value = ((value << 5) + value) + (*str);
   	}

	FLOG_OUT(fname);
 	return value;
}

unsigned int rp_hash_dek(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_dek";
	static char msg[] = "fatal error";
	Err err;
   	unsigned int value = len;
   	unsigned int i = 0;
	FLOG_IN(fname);
	
   	for (i = 0; i < len; str++, i++)
   	{
      		value = ((value << 5) ^ (value >> 27)) ^ (*str);
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_bp(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_bp";
	static char msg[] = "fatal error";
	Err err;
   	unsigned int value = 0;
   	unsigned int i = 0;
	FLOG_IN(fname);
	
   	for (i = 0; i < len; str++, i++)
   	{
      		value = value << 7 ^ (*str);
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_fnv(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_fnv";
	static char msg[] = "fatal error";
	Err err;
   	const unsigned int fnv_prime = 0x811C9DC5;
   	unsigned int value = 0;
   	unsigned int i = 0;
	FLOG_IN(fname);
	
   	for (i = 0; i < len; str++, i++)
   	{
      		value *= fnv_prime;
      		value ^= (*str);
   	}

	FLOG_OUT(fname);
   	return value;
}

unsigned int rp_hash_ap(char* str, unsigned int len)
{
	static char fname[] = "rp_hash_ap";
	static char msg[] = "fatal error";
	Err err;
   	unsigned int value = 0xAAAAAAAA;
   	unsigned int i    = 0;
	FLOG_IN(fname);
	
   	for (i = 0; i < len; str++, i++)
   	{
      		value ^= ((i & 1) == 0) ? (  (value <<  7) ^ (*str) * (value >> 3)) :
                               (~((value << 11) + (*str) ^ (value >> 5)));
   	}

	FLOG_OUT(fname);
   	return value;
}

